package py.com.alfa.escriba.gui.controller;

import java.io.Serializable;
import java.util.Locale;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.servlet.HandlerMapping;
import org.winter.utils.command.ControllerObject;

import py.com.alfa.escriba.gui.exception.ExceptionHandler;
import py.com.alfa.escriba.gui.rest.services.AdminService;
import py.com.alfa.escriba.gui.session.AuthenticationInfo;
import py.com.alfa.escriba.gui.session.SystemInfo;
import py.com.alfa.escriba.gui.session.SystemSessionManager;
import py.com.alfa.escriba.gui.spring.processors.SpringBean;
import py.com.alfa.escriba.gui.utils.ObjectUtils;


@Controller
@Scope("session")
@SessionAttributes({AttributesNames.AUTHENTICATION_INFO})
public class HomeController implements Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = 7756316160518670180L;
	private static final Logger logger = LoggerFactory.getLogger(HomeController.class);
	

	@SpringBean private SystemInfo systemInfo;
	@SpringBean private SystemSessionManager systemSessionManager;
	@SpringBean private AdminService adminService;
	
	private Locale locale;
	
	@ControllerObject
	private AuthenticationInfo authInfo;
	
	public HomeController() {
		loadObjects();		
	}

	private void loadObjects() {
		setLocale(LocaleContextHolder.getLocale());		
	}

	/**
	 * Configure Layout.
	 */
	@RequestMapping(value = "/layout", method = RequestMethod.GET)
	public String layout(Model model) {
		logger.info("---Loading Layout");
		return "/layouts/layout";
	}
	
	/**
	 * Simply selects the home view to render by returning its name.
	 */	
	@RequestMapping(value = "/", method = RequestMethod.GET)
	public String homePage(Model model, HttpServletRequest request, HttpServletResponse response) {
		logger.info("\n==============\nWelcome to PRIVA-GUI!\n==============\n");
		model.addAttribute(AttributesNames.AUTHENTICATION_INFO, getAuthInfo());
		Boolean permitted = false;
		Subject currentUser = SecurityUtils.getSubject();

		try{
		  logger.info("\n==============\nis Authenticated: {}\n==============\n", currentUser.isAuthenticated());
		  if(!currentUser.isAuthenticated()) {
		    systemInfo.setSystemError(false);
		    systemInfo.setErrorMessage("");
	        return "login";
	      }
	      permitted = true;
	    
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
		}
		logger.info("\n==============\nPermitted: {}\n==============\n", permitted);
		
		if(permitted){
			systemInfo.setSystemError(false);
			systemInfo.setErrorMessage("");
		}
		if(!permitted){
			logger.info("\n==============\nNOT Permitted: \n==============\n");
			systemInfo.setSystemError(true);
			systemInfo.setErrorMessage("El usuario no esta autorizado para utilizar este recurso");
		}
		
		if(systemInfo.getSystemError()){
			return "error";
		}
		
		return "home";
	}
	
	/**
	   * Simply selects the home view to render by returning its name.
	   */
	  @RequestMapping(value = "/login", method = RequestMethod.POST)
	  public String loginPage(Model model, HttpServletRequest request, HttpServletResponse response,
	      @ModelAttribute(AttributesNames.AUTHENTICATION_INFO) AuthenticationInfo authInfo,
	      BindingResult result) {
		  
	    logger.info("\n==============\nLogin to PRIVA-GUI!\n==============\n");
	    try {
	      logger.info("\n==============\n request User: {}\n==============\n", authInfo.getUsername());
	      String id = request.getSession().getId();
	      logger.info("ID: {}", id);
	      systemSessionManager.init(getAuthInfo());
	      if ( !systemInfo.getAuthenticated()) {
		      systemInfo.setSystemError(true);
		      systemInfo.setErrorMessage("");	    	  
	      }
	      
	      if(systemInfo.getIdEscribano() != null){
	    	  systemInfo.setEscribano(adminService.obtenerEscribano(systemInfo.getIdEscribano()));
	      }
	      
	      systemInfo.setUserName(id);
	      systemInfo.setAuthenticated(true);
	      String urlFragment = (String) request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE);
	      logger.info("REQUEST PATH: {}", urlFragment);
	      systemInfo.setPagePath(urlFragment);
	      systemInfo.setSystemError(false);
	      systemInfo.setErrorMessage("");
	      this.authInfo = new AuthenticationInfo();
	      return "redirect:/";
	    } catch (Exception e) {
	      logger.error("\n==============\nLOGIN ERROR!\n==============\n : {}", e);
	      String message = ExceptionHandler.handle(e, getLocale(), getClass());
	      return "redirect:/login/"+message;
	    }
	    
	  }
	  
	  @RequestMapping(value = "/login/{message}", method = RequestMethod.GET)
	  public String loginPage(Model model, HttpServletRequest request, HttpServletResponse response, @PathVariable("message") String message) {
		  logger.info("\n==============\nLogin with message: {}\n==============\n", message);
		    if(!ObjectUtils.isEmpty(message)){
		      systemInfo.setSystemError(true);
		      systemInfo.setErrorMessage(message);
		    }
	    model.addAttribute(AttributesNames.AUTHENTICATION_INFO, getAuthInfo());
	    return "login";
	  }
	
	/**
	 * Single sing Logout.
	 */
	@RequestMapping(value = "/logout", method = RequestMethod.GET)
	public String logout(Model model, HttpServletRequest request) {
		logger.info("\n==============\nDesconnecting!\n==============\n");
		Subject currentUser = SecurityUtils.getSubject();
		if(currentUser.isAuthenticated()){
			logger.info("\n==============\nLogout!\n==============\n");
			currentUser.logout();
		}
		this.authInfo = new AuthenticationInfo();
		return "redirect:/login/"+"Cierre de sesion correcto.";
	}
	
	
	@RequestMapping(value = "/error", method = RequestMethod.GET)
	public String errorPage(Model model, HttpServletRequest request,
			HttpServletResponse response) {
		logger.info("\n==============\nWelcome to PRIVA-GUI!\n==============\n");
		return "error";
	}
	
	  /**
	   * @return the authInfo
	   */
		
	  @ModelAttribute(AttributesNames.AUTHENTICATION_INFO)
	  public AuthenticationInfo getAuthInfo() {
	    return authInfo;
	  }
	
	  /**
	   * @param authInfo the authInfo to set
	   */
	  public void setAuthInfo(AuthenticationInfo authInfo) {
	    this.authInfo = authInfo;
	  }

	  public Locale getLocale() {
		  return locale;
	  }

	  public void setLocale(Locale locale) {
		  this.locale = locale;
	  }	  
}
